package cn.edu.pku.nggis.remotesensingdigitalimageprocessing;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MinimalDistanceClassifyProcess implements ClassifyProcess {

	protected class muRecord implements Comparable<muRecord> {
		public int rgb;
		public long[] samples;

		public muRecord(int i) {
			rgb = i;
			samples = new long[MainProcess.BANDNUM];
		}

		@Override
		public int compareTo(muRecord arg0) {
			return Integer.compare(rgb, arg0.rgb);
		}
	}

	public void classify(List<muRecord> muList, int[][][] dataArray,
			int[][] classifiedArray) {
		double distance;
		int classnum = 0;
		long diff;
		for (int i = 0; i < MainProcess.WIDTH; i++) {
			for (int j = 0; j < MainProcess.HEIGHT; j++) {
				distance = Double.MAX_VALUE;
				for (int k = 0; k < muList.size(); k++) {
					long[] samples = muList.get(k).samples;
					long kd = 0;
					for (int ite = 0; ite < samples.length; ite++) {
						diff = samples[ite] - dataArray[i][j][ite];
						kd += diff * diff;
					}
					if (kd < distance) {
						classnum = muList.get(k).rgb;
						distance = kd;
					}
				}
				classifiedArray[i][j] = classnum;
			}
		}
	}

	protected List<muRecord> getMuList(Map<Integer, List<Point>> samplePixels,
			int[][][] dataArray) {
		List<muRecord> muList = new ArrayList<muRecord>();
		Set<Entry<Integer, List<Point>>> mapentry = samplePixels.entrySet();
		for (Entry<Integer, List<Point>> entry : mapentry) {
			muList.add(new muRecord(entry.getKey()));
			long[] samples = muList.get(muList.size() - 1).samples;
			List<Point> pl = entry.getValue();
			for (Point p : pl) {
				for (int ite = 0; ite < samples.length; ite++) {
					samples[ite] += dataArray[p.x][p.y][ite];
				}
			}
			for (int ite = 0; ite < samples.length; ite++) {
				samples[ite] = samples[ite] / pl.size();
			}
		}
		return muList;
	}

	@Override
	public void process(Map<Integer, List<Point>> samplePixels,
			int[][] classifiedArray, int[][][] dataArray,
			Map<String, Object> params) {
		List<muRecord> muList = getMuList(samplePixels, dataArray);
		classify(muList, dataArray, classifiedArray);
	}

}
